package com.sunseaypw.db.mybits;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class Mybits {
    public static void main(String[] args){
        ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("mybits.xml");
        var stBean=ctx.getBean(StudentDAO.class);
        //var st= stBean.getStudentById(12);
        // System.out.println(st);
        //stBean.getStudentByName("天龙在家");
        stBean.operate1(ctx);

        // try (SqlSession session = sqlSessionFactory.openSession()) {
        //     Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
        //   }

        // try (SqlSession session = sqlSessionFactory.openSession()) {
        //     BlogMapper mapper = session.getMapper(
        //   BlogMapper.class
        //   );
        //     Blog blog = mapper.selectBlog(101);
        //   }
    }
    
    /**自定义注解一定要设置为RUNTIME以便运行期被反射 */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MybatisMapper{
    }
    /* 自动扫描mapper
     * 
     */
    @Configuration 
    //默认扫描包路径下的所有接口   
    @MapperScan(basePackages = {"com.sunseaypw.db.mybits", "com.sunseaypw.db.mybits"}, 
        annotationClass = MybatisMapper.class)
    public static class MyBatisConfig {
    }

    /**添加标记注解，以便被定位 */
    @MybatisMapper
    public static interface StudentMapper {
        @Select("SELECT * FROM students WHERE id = #{id}")
        Student getById(@Param("id") long id);
        @Select("SELECT * FROM students WHERE name = #{name} limit 3")
        List<Student> getAll(@Param("name") String name);

        @Update("UPDATE students SET name = #{st.name} WHERE id = #{st.id}")
        void update1(@Param("st") Student st);
        @Update("UPDATE students SET name222 = #{st.name} WHERE id = #{st.id}")
        void update2(@Param("st") Student st);
    }
    //没有标记注解，所以不会被mapper—scan识别到
    public static interface aaaaaaaa {
        @Select("SELECT * FROM students WHERE id = #{id}")
        Student getById(@Param("id") long id);        
    }

    public static class Student {
        private Long id;
        private String name;
        private int grade;
        private int score;
        public String toString(){
            return String.format("id=%s name=%s grade=%s ", this.id,this.name,this.grade);
        }
    }

    @Component
    public static class StudentDAO{          
        @Autowired
        StudentMapper studentMapper;
        
        @Autowired
        StudentDAO proxySelf;

        public Student getStudentById(long id) {
            // 调用Mapper方法:
            Student st = studentMapper.getById(id);
            if (st == null) {
                throw new RuntimeException("Student not found by id.");
            }
            return st;
        }

        public void getStudentByName(String name) {
            // 调用Mapper方法:
            var lsst = studentMapper.getAll(name);
            if (lsst.size() <=0 ) {
                throw new RuntimeException("Student not found by id.");
            }
            for(var st : lsst){
                System.out.println(st);
            }
        }

        @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
        public void operate1(ClassPathXmlApplicationContext ctx) {
            var con=DataSourceUtils.getConnection(ctx.getBean(JdbcTemplate.class).getDataSource());
            System.out.println(con);    
            try{
                proxySelf.operate2(ctx);
            }catch(Exception ex){

            }
            var st=new Student();
            st.name="第一次啊啊啊111111111111111111111111";
            st.id=Long.valueOf(21);
            studentMapper.update1(st);
            var st2=new Student();
            st2.name="第二次啊啊啊222222222222222222222222";
            st2.id=Long.valueOf(22);
            studentMapper.update2(st2);
            
        }

        @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
        public void operate2(ClassPathXmlApplicationContext ctx) {
            var con=DataSourceUtils.getConnection(ctx.getBean(JdbcTemplate.class).getDataSource());
            System.out.println(con);     
            var st=new Student();
            st.name="第一次啊啊啊111111111111111111111111";
            st.id=Long.valueOf(23);
            studentMapper.update1(st);
            var st2=new Student();
            st2.name="第二次啊啊啊222222222222222222222222";
            st2.id=Long.valueOf(24);
            studentMapper.update1(st2);
        }
    }
}
